/*************************************************************************
 *
 * rutiny power managementu
 * 
 * (c) Ales Povalac, alpov@alpov.net, http://www.alpov.net/
 * 
 *************************************************************************
 *
 * $Id: pwrman.c 85 2006-08-31 15:35:48Z alpov $
 * 
 *************************************************************************/         

#include <stdint.h>
#include "../avrx/avrx.h"
#include "../avrx/AvrXFifo.h"
#include <avr/interrupt.h>
#include "pwrman.h"
#include "log.h"
#include "sensor.h"
#include "serial.h"


/*************************************************************************
 * inicializace manageru
 *************************************************************************/ 
void InitPowerManagement(void)
{
    // inicializace A/D prevodniku
    ADCSRA = /*_BV(ADEN) |*/ _BV(ADPS2) | _BV(ADPS1);
    
    // inicializace externiho interruptu
    MCUCR |= _BV(ISC10);    // ISC00
    GIFR = _BV(INTF1);      // INFO0
    // FIXME: GICR |= _BV(INT1);      // INT0
}


/*************************************************************************
 * ISR zmeny na cidlu sitoveho napajeni
 *************************************************************************/ 
AVRX_SIGINT(INT1_vect)      // INT0_vect
{
/*
    static unsigned char saved_ddr[4];
*/
    
    IntProlog();
    EndCritical();
    
    if (power_present) {
        // napajeni obnoveno
/*
        DDRA = saved_ddr[0];
        DDRB = saved_ddr[1];
        DDRC = saved_ddr[2];
        DDRD = saved_ddr[3];
        SFIOR &= ~_BV(PUD);
*/
        AvrXResume(PID(SensorTask));
        AvrXResume(PID(SerialTask));
        
        // LogWrite(); FIXME: v interruptu?! nelze! predelat log na task a resit pomoci fifo
        
    } else {
        // vypadek napajeni
        AvrXSuspend(PID(SensorTask));
        AvrXSuspend(PID(SerialTask));
        
        // LogWrite();
/*
        saved_ddr[0] = DDRA;
        saved_ddr[1] = DDRB;
        saved_ddr[2] = DDRC;
        saved_ddr[3] = DDRD;
        DDRA = 0;
        DDRB = 0;
        DDRC = 0;
        DDRD = 0;
        SFIOR |= _BV(PUD);
*/
    }
    
    Epilog();
}


/*************************************************************************
 * cteni A/D hodnoty napeti
 *************************************************************************/ 
unsigned int ReadVoltage(unsigned char mux)
{
    int i;
    unsigned int result = 0;
    
    ADMUX = _BV(REFS1) | _BV(REFS0) | mux;
    
    ADCSRA |= _BV(ADEN) | _BV(ADSC);
    loop_until_bit_is_clear(ADCSRA, ADSC);
    
    for (i = 0; i < 8; i++) {
        ADCSRA |= _BV(ADSC);
        loop_until_bit_is_clear(ADCSRA, ADSC);
        result += (ADCL);
        result += (ADCH << 8);
    }
    
    result >>= 3;
    
    ADCSRA &= ~_BV(ADEN);
    
    return result;
}

